package personal.vap.route.tracker.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@SuppressWarnings("serial")
public class RouteTrackerServerServlet extends HttpServlet {

  public static final String LIST_COMMAND = "list";
  private static final String TEXT_JSON = "text/json";
  private static final String UTF_8 = "UTF-8";

  private static final Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new JsonUtils.MyJsonSerializer()).registerTypeAdapter(Date.class, new JsonUtils.MyJsonDeserializer()).create();

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    request.setCharacterEncoding(UTF_8);

    response.setContentType(TEXT_JSON);
    response.setCharacterEncoding(UTF_8);
    try {
      String[] restPath = getCommandPath(request);
      
      RESTResponse restResponse = null;
      if (LIST_COMMAND.equals(restPath[1])) {
        restResponse = RouteManager.getInstance().getListCommandResponse();
      } else if ("details".equals(restPath[1])) {
        if (restPath.length < 3) {
          throw new ErrorResponseException(400, "Route details request without a name");
        }
        String routeName = URLDecoder.decode(restPath[2], UTF_8);
        restResponse = RouteManager.getInstance().getRouteDetailsResponse(routeName);
      }
      
      writeSuccessResponse(response, restResponse);
    } catch (ErrorResponseException e) {
      writeErrorResponse(e, response);
    }
  }

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    request.setCharacterEncoding(UTF_8);

    response.setContentType(TEXT_JSON);
    response.setCharacterEncoding(UTF_8);
    
    InputStream input = request.getInputStream();
    Route route = gson.fromJson(new InputStreamReader(input, UTF_8), Route.class);
    RouteManager.getInstance().addRoute(route);
    RESTResponse restResponse = new RESTResponse();
    restResponse.statusCode = 200;
    restResponse.message = "Route added";
    
    writeSuccessResponse(response, restResponse);
  }
  
  @Override
  public void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
  }
  
  @Override
  public void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    writeErrorResponse(new ErrorResponseException(500, "Not supported"), response);
  }

  private void writeErrorResponse(ErrorResponseException e, HttpServletResponse response) throws IOException {
    RESTResponse errorResponse = new RESTResponse();
    errorResponse.message = e.getMessage();
    errorResponse.statusCode = e.getErrorCode();
    writeSuccessResponse(response, errorResponse);
    response.setStatus(e.getErrorCode());
  }

  private String[] getCommandPath(HttpServletRequest request) throws ErrorResponseException {
    String requestURI = request.getRequestURI();
    String contextPath = request.getContextPath();
    if (requestURI.length() <= contextPath.length()) {
      throw new ErrorResponseException(400, "Invalid path");
    }
    String servletPath = requestURI.substring(contextPath.length() + 1);
    String[] restPath = servletPath.split("/");
    return restPath;
  }
  
  private void writeSuccessResponse(HttpServletResponse response, RESTResponse restResponse) throws IOException {
    String responseStr = gson.toJson(restResponse);
    response.getWriter().print(responseStr);
  }
  
}
